package com.app.core.validator;

import java.lang.reflect.InvocationTargetException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;

import com.app.core.util.Out;

public class ValidateBean {

    public static ValidatorResult vali(Object obj, String ruleName) {
        ValidatorConfig config = ValidatorContext.configMap.get(ruleName);
        return startVal(obj, config);
    }

    public static ValidatorResult vali(Object obj, Class<?> ruleName) {
        ValidatorConfig config = ValidatorContext.configMap.get(ruleName.getName());
        return startVal(obj, config);
    }

    public static ValidatorResult vali(Object obj) {

        ValidatorConfig config = ValidatorContext.bean(obj.getClass());

        return startVal(obj, config);
    }

    private static ValidatorResult startVal(Object obj, ValidatorConfig config) {
        ValidatorResult result = new ValidatorResult();
        if (config == null) {
            return result;
        }
        Map<String, Map<String, String>> rules = config.getRules();
        if (rules == null) {
            return result;
        }

        /*
         * 对哪些字段进行校验
         */
        boolean validatAll = false;
        boolean hasError = false;
        Set<String> keySet = rules.keySet();
        for (String field : keySet) {
            if (!validatAll && hasError) {
                throw new ValidateMsgException(result);
            }
            String property;
            try {
                property = BeanUtils.getProperty(obj, field);
            } catch (NoSuchMethodException e) {
                Out.w("校验bean警告, " + obj.getClass() + " 没有此字段" + field);
                continue;
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new ValidateException(e);
            }

            Map<String, String> ruleMap = rules.get(field);
            Set<String> keySet2 = ruleMap.keySet();
            for (String key : keySet2) {
                if (key.equals("required") && StringUtils.isBlank(property)) {
                    hasError = true;
                    error(result, config, field, key);
                    break;
                }else if (key.equals("selectNotNull") && "-1".equals(property)) {
                    hasError = true;
                    error(result, config, field, key);
                    break;
                } else if (key.equals("maxlength") && property.length() > Integer.parseInt(ruleMap.get(key))) {
                    hasError = true;
                    error(result, config, field, key);
                    break;
                } else if (key.equals("minlength") && property.length() < Integer.parseInt(ruleMap.get(key))) {
                    hasError = true;
                    error(result, config, field, key);
                    break;
                } else if (key.equals("max") && (StringUtils.isNotBlank(property) && Double.parseDouble(property) > Double.parseDouble(ruleMap.get(key)))) {
                    hasError = true;
                    error(result, config, field, key);
                    break;
                } else if (key.equals("min") && (StringUtils.isNotBlank(property) && Double.parseDouble(property) < Double.parseDouble(ruleMap.get(key)))) {
                    hasError = true;
                    error(result, config, field, key);
                    break;
                } else if (key.equals("digits") && !ValidatorUtil.isDigits(property)) {
                    hasError = true;
                    error(result, config, field, key);
                    break;
                } else if (key.equals("number") && !ValidatorUtil.isNumber(property, 100)) {
                    hasError = true;
                    error(result, config, field, key);
                    break;
                } else if (key.equals("url") && !ValidatorUtil.isUrl(property)) {
                    hasError = true;
                    error(result, config, field, key);
                    break;
                } else if (key.equals("email") && !ValidatorUtil.isEmail(property)) {
                    hasError = true;
                    error(result, config, field, key);
                    break;
                }
            }
        }

        if (!validatAll && hasError) {
            throw new ValidateMsgException(result);
        }

        return result;
    }

    private static void error(ValidatorResult result, ValidatorConfig config, String field, String key) {
    	Map<String, Map<String, String>> rules = config.getRules();
        Map<String, Map<String, String>> messages = config.getMessages();
        Map<String, String> names = config.getNames();
        String msg = "";
        String fieldName = null;
        if (names != null && names.containsKey(field)) {
            fieldName = names.get(field);
        }

        if (messages == null || messages.get(field) == null || messages.get(field).get(key) == null) {
            msg += ValidatorContext.defaultMsg.get(key);
        } else {
            msg += messages.get(field).get(key);
        }
        
        if("minlength".equals(key)){
        	msg = msg.replace("{0}", rules.get(field).get("minlength"));
        }
        if("maxlength".equals(key)){
        	msg = msg.replace("{0}", rules.get(field).get("maxlength"));
        }
        
        if (result.isValidateAll()) {
            Map<String, String> all = result.getAll();
            if (all == null) {
                all = new LinkedHashMap<String, String>();
            }
            all.put(field, msg);
        } else {
            result.setFieldName(fieldName);
            result.setField(field);
            result.setMsg(fieldName + ":  " + msg);
        }
    }

}
